﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

using Microsoft.SPOT.Net.NetworkInformation;
using System.Text;
using System.IO;
using mfRCF.Rss;
using mfXmlSerializer;

namespace mfRCF.NetduinoPlus2.RSSRawTest.TestApp
{
    public class Program
    {
        static rss _rssSample = RSSSampleDataFactory.CreateRSSSample_Complete();
        static mfXmlTypedSerializer _rssSerializer = new mfXmlTypedSerializer(_rssSample.GetType());

        public static void Main()
        {
            PrintCpuInfo();

            //hang in rssVersionWriterAction in serialzation-process
            _rssSerializer.ElementSerialized += mfWriteRSSVersionAction.WriteRSSVersionAction;

            // write your code here
            InitializeNetworkInterface();

            Thread.Sleep(10000);

            var thHttpListener = new Thread(new ThreadStart(HandleHttpAsync));
            thHttpListener.Start();
        }

        private static void PrintCpuInfo()
        {
            Debug.Print("cpu-clock: " + Cpu.SystemClock);
            Debug.Print("slow-clock: " + Cpu.SlowClock);
        }

        private static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
        {
            Debug.Print("NetworkAvailabilityChanged --> Availability:" + e.IsAvailable);

        }

        private static void InitializeNetworkInterface()
        {
            var netIOs = NetworkInterface.GetAllNetworkInterfaces();

            NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;

            foreach (var netIO in netIOs)
            {
                netIO.EnableStaticIP("192.168.70.106", "255.255.255.0", "192.168.70.254");
                netIO.EnableStaticDns(new string[] { "192.168.70.254" });

            }
            Debug.Print("Network initialized");
        }

        private static void HandleHttpAsync()
        {
            var httpListener = new HttpListener("http", 80);
            httpListener.Start();
            
            HttpListenerContext context = null;

            object _sync = new object();

            while (true)
            {
                try
                {
                    lock (_sync)
                    {
                        context = httpListener.GetContext();
                        if (context == null)
                        {
                            continue;
                        }

                        BuildNWriteResponse(context);
                    }
                }
                catch (InvalidOperationException ioex)
                {
                    Debug.Print("InvalidOperationException: " + ioex.Message);
                }
                catch (Exception ex)
                {
                    Debug.Print("HttpHandle Error: " + ex.Message);
                }
            }
        }
            
        private static void BuildNWriteResponse(HttpListenerContext context)
        {
            try
            {
                //Logger.Info("request from " + context.Request.RemoteEndPoint.Address
                //+ ":" + context.Request.RemoteEndPoint.Port
                //+ " @http://" + context.Request.UserHostAddress + context.Request.RawUrl + " received");

                String strContent = String.Empty;

                if (context.Request.RawUrl == "/rss")
                {
                    strContent = _rssSerializer.Serialize(_rssSample);
                    context.Response.StatusCode = 200;//=OK
                }
                else if (context.Request.RawUrl == "/" 
                    && context.Request.HttpMethod == "POST")
                {
                    Debug.Print("POST on / with length " + context.Request.InputStream.Length + " received");
                    if (context.Request.InputStream.Length > 0)
                    {
                        var byteContent = new byte[context.Request.InputStream.Length];
                        context.Request.InputStream.Read(byteContent, 0, (int)context.Request.InputStream.Length);

                        Debug.Print("Content: ");
                        Debug.Print(new string(System.Text.UTF8Encoding.UTF8.GetChars(byteContent)));
                    }

                    context.Response.StatusDescription = "asdfasdf description";
                    context.Response.StatusCode = 200;
                }
                else if (context.Request.RawUrl == "/" //'/rss?name=asdf&date=01.01.2014'
                    && context.Request.HttpMethod == "GET")//192.168.70.106/rss?name=asdf&date=01.01.2014
                {
                    Debug.Print("POST on / with length " + context.Request.InputStream.Length + " received");
                    if (context.Request.InputStream.Length > 0)
                    {
                        var byteContent = new byte[context.Request.InputStream.Length];
                        context.Request.InputStream.Read(byteContent, 0, (int)context.Request.InputStream.Length);

                        Debug.Print("Content: ");
                        Debug.Print(new string(System.Text.UTF8Encoding.UTF8.GetChars(byteContent)));
                    }

                    context.Response.StatusDescription = "asdfasdf description";
                    context.Response.StatusCode = 200;
                }
                else
                {
                    strContent = "'" + context.Request.RawUrl + "' is an invalid Request";
                    context.Response.StatusCode = 404;//=Resource not found
                }

                var responseBytes = Encoding.UTF8.GetBytes(strContent);
                context.Response.ContentType = "text/html";

                try
                {
                    context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
                }
                finally
                {
                    context.Response.Close();
                }
            }
            catch (Exception ex)
            {
                //bad, but otherwise 4 each request a NetSocketException (Errorcode=10053=WSAECONNABORTED 'Software caused connection abort') will be thrown...
                Debug.Print(ex.Message);
            }
        }

    }
}
